package de.steric.battlemon.rendering;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.vector.Matrix4f;

import static org.lwjgl.opengl.GL11.*;
import de.steric.battlemon.Battlemon;
import de.steric.battlemon.GameObject;

public class Graphics extends Thread {
	public int width, height;
	public Battlemon battlemon;

	public static Graphics graphics;

	private HashMap<String, Mesh> meshList;
	private float fps;
	public Camera camera;
	private Shader meshShader;
	public Graphics(Battlemon b, int width, int height) {
		graphics = this;
		this.height = height;
		this.width = width;
		battlemon = b;
		fps = 0;
	}

	private void init() throws LWJGLException, ParseException, Exception {
		System.out.println("Initializing Graphics");
		Display.create();
		Display.setDisplayMode(new DisplayMode(width, height));
		meshList = new HashMap<>();
		camera=new Camera();
		camera.width=width;
		camera.height=height;
		loadMeshes();
		loadShader();
		synchronized (battlemon) {
			System.out.println("Wake up Battlemon");
			battlemon.notify();// notify Battlemon to proceed
			System.out.println("Waiting for Battlemon to initialize");
			battlemon.wait();
		}
	}

	private void loadMeshes() throws ParseException {
		System.out.println("Loading Meshes");
		loadMesh("./Models/Battlemon/Simonsky.obj");
	}

	private void loadShader() throws Exception {
		meshShader=Shader.loadShader("./Shader/MeshVertexShader.shader","./Shader/MeshFragmentShader.shader");
		System.out.println("Loaded Mesh Shader");
	}

	

	private void loadMesh(String name) throws ParseException {
		ObjParser parser = new ObjParser(name);
		Mesh m=parser.loadMesh();
		System.out.println("Mesh "+m.name+" loaded from "+ name);
		meshList.put(m.name,m);
	}
	
	public void run() {

		try {
			init();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			System.exit(1);
		}
		System.out.println("Starting Graphics Loop.");
		long lastTime = System.currentTimeMillis();
		
		while (!battlemon.isCloseRequested) {
			float delta = (System.currentTimeMillis() - lastTime);
			if (delta != 0)
				fps = 1000 / delta;
			else
				fps = 999;
			lastTime = System.currentTimeMillis();
			paint();
			input();
			Display.update();
			Display.sync(Battlemon.fps);
		}
		Display.destroy();
	}

	public Mesh getMesh(String name) {
		return meshList.get(name);
	}
	public Shader getMeshShader()
	{
		return meshShader;
	}
	private void paint() {
		Display.setTitle("Battlemon @ " + fps + " FPS");
		render3D();
		
	}
	private void render3D()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
				| GL_STENCIL_BUFFER_BIT);
		camera.setViewProjection();
		
		GameObject origin = battlemon.getSzene();
		origin._render();
	}
	private void input() {
		if (Display.isCloseRequested())
			battlemon.requestClose();

	}
}
